package com.gitee.wsl.doc.prosemirror.transform.internal
//
//import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
//import com.gitee.wsl.doc.prosemirror.model.node.Node
//import com.gitee.wsl.doc.prosemirror.model.content.ext.coveredDepths
//import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
//import com.gitee.wsl.doc.prosemirror.model.fragment.ext.closeFragment
//import com.gitee.wsl.doc.prosemirror.model.fragment.ext.fitsTrivially
//import com.gitee.wsl.doc.prosemirror.model.node.isDefinesContent
//import com.gitee.wsl.doc.prosemirror.model.node.ext.insertPoint
//import com.gitee.wsl.doc.prosemirror.model.node.ext.resolveSafe
//import com.gitee.wsl.doc.prosemirror.transform.TransformAble
//import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceStep
//import kotlin.math.abs
//
//
//@Suppress("LongMethod", "ComplexMethod")
//internal fun <T: TransformAble> replaceRange(tr: T, from: Int, to: Int, slice: Slice): T? {
//    if (slice.size == 0) return tr.deleteRange(from, to)
//    val (_from, _to) = tr.doc.resolveSafe(from, to) ?: return null
//    if (slice.fitsTrivially(_from, _to)) {
//        return tr.step(ReplaceStep(from, to, slice))
//    }
//
//    val targetDepths = coveredDepths(_from, tr.doc.resolve(to)).toMutableList()
//    // Can't replace the whole document, so remove 0 if it's present
//    if (targetDepths.getOrNull(targetDepths.size - 1) == 0) targetDepths.removeLast()
//    // Negative numbers represent not expansion over the whole node at
//    // that depth, but replacing from $from.before(-D) to $to.pos.
//    var preferredTarget = -(_from.depth + 1)
//    targetDepths.add(0, preferredTarget)
//    // This loop picks a preferred target depth, if one of the covering
//    // depths is not outside of a defining node, and adds negative
//    // depths for any depth that has $from at its start and does not
//    // cross a defining node.
//    var d = _from.depth
//    var pos = _from.pos - 1
//    while (d > 0) {
//        val spec = _from.node(d).type.spec
//        if (spec.defining == true || spec.definingAsContext == true || spec.isolating == true) break
//        if (targetDepths.indexOf(d) > -1) {
//            preferredTarget = d
//        } else if (_from.before(d) == pos) {
//            targetDepths.add(1, -d)
//        }
//        d--
//        pos--
//    }
//    // Try to fit each possible depth of the slice into each possible
//    // target depth, starting with the preferred depths.
//    val preferredTargetIndex = targetDepths.indexOf(preferredTarget)
//
//    val leftNodes = mutableListOf<Node?>()
//    var preferredDepth = slice.openStart
//    var content = slice.content
//    var i = 0
//    while (true) {
//        val node = content.firstChild
//        leftNodes.add(node)
//        if (i == slice.openStart) break
//        content = node!!.content
//        i++
//    }
//
//    // Back up preferredDepth to cover defining textblocks directly
//    // above it, possibly skipping a non-defining textblock.
//    for (d in preferredDepth - 1 downTo 0) {
//        val leftNode = leftNodes[d] ?: continue
//        val def = leftNode.type.isDefinesContent()
//        if (def && !leftNode.sameMarkup(_from.node(abs(preferredTarget) - 1))) {
//            preferredDepth = d
//        } else if (def || !leftNode.type.isTextblock) {
//            break
//        }
//    }
//
//    for (j in slice.openStart downTo 0) {
//        val openDepth = (j + preferredDepth + 1) % (slice.openStart + 1)
//        val insert = leftNodes[openDepth] ?: continue
//        for (i in targetDepths.indices) {
//            // Loop over possible expansion levels, starting with the
//            // preferred one
//            var targetDepth = targetDepths[(i + preferredTargetIndex) % targetDepths.size]
//            var expand = true
//            if (targetDepth < 0) {
//                expand = false
//                targetDepth = -targetDepth
//            }
//            val parent = _from.node(targetDepth - 1)
//            val index = _from.index(targetDepth - 1)
//            if (parent.canReplaceWith(index, index, insert.type, insert.marks)) {
//                return tr.replace(
//                    _from.before(targetDepth),
//                    if (expand) _to.after(targetDepth) else to,
//                    Slice(
//                        slice.content.closeFragment( 0, slice.openStart, openDepth),
//                        openDepth,
//                        slice.openEnd
//                    )
//                )
//            }
//        }
//    }
//
//    val startSteps = tr.steps.size
//    var from = from
//    var to = to
//    @Suppress("LoopWithTooManyJumpStatements")
//    for (i in targetDepths.size - 1 downTo 0) {
//        tr.replace(from, to, slice)
//        if (tr.steps.size > startSteps) break
//        val depth = targetDepths[i]
//        if (depth < 0) continue
//        from = _from.before(depth)
//        to = _to.after(depth)
//    }
//    return null
//}
//
//
//internal fun replaceRangeWith(tr: Transform, from: Int, to: Int, node: Node) {
//    var from = from
//    var to = to
//    if (!node.isInline && from == to && tr.doc.resolve(from).parent.content.size != 0) {
//        val point = tr.doc.insertPoint(from, node.type)
//        if (point != null) {
//            to = point
//            from = to
//        }
//    }
//    tr.replaceRange(from, to, Slice(Fragment.from(node), 0, 0))
//}
//
//internal fun deleteRange(tr: Transform, from: Int, to: Int): Transform {
//    val (_from, _to) = tr.doc.resolveSafe(from, to) ?: return tr
//    val covered = coveredDepths(_from, _to)
//    for (i in 0 until covered.size) {
//        val depth = covered[i]
//        val last = i == covered.size - 1
//        if ((last && depth == 0) || _from.node(depth).type.contentMatch.validEnd) {
//            return tr.delete(_from.start(depth), _to.end(depth))
//        }
//        if (depth > 0 &&
//            (
//                last || _from.node(depth - 1)
//                    .canReplace(_from.index(depth - 1), _to.indexAfter(depth - 1))
//                )
//        ) {
//            return tr.delete(_from.before(depth), _to.after(depth))
//        }
//    }
//    var d = 1
//
//    while (d <= _from.depth && d <= _to.depth) {
//        if (
//            from - _from.start(d) == _from.depth - d &&
//            to > _from.end(d) && _to.end(d) - to != _to.depth - d &&
//            _from.start(d - 1) == _to.start(d - 1) &&
//            _from.node(d - 1).canReplace(_from.index(d - 1), _to.index(d - 1))
//        ) {
//            return tr.delete(_from.before(d), to)
//        }
//        d++
//    }
//    return tr.delete(from, to)
//}
